<?php
// @formatter:off
/**
 * @file WCGTableRepresentation.abs.php
 * @author Alejandro Dario Simi
 * @date $Date: 2013-06-22 17:58:11 +0000 (Sat, 22 Jun 2013) $
 *
 * $Id: WCGTableRepresentation.abs.php 83 2013-06-22 17:58:11Z daemonraco@gmail.com $
 * $URL: http://wcomix.googlecode.com/svn/tags/wcomix-1.0-BETA2/includes/representations/WCGTableRepresentation.abs.php $
 */
// @formatter:on

/**
 * @abstract
 * @class WCGTableRepresentation
 */
abstract class WCGTableRepresentation extends WCRepresentation {
	protected $_PropertiesReadOnly = array(
		"id",
		"group"
	);

	/**
	 * @var WCGroup
	 */
	protected $_group = null;

	//
	// Public methods.
	/**
	 * This pseudo-method gives an easy way to modify database columns for a
	 * specific row represented by this object. For example, given a table
	 * with columns named col_% (set by $_PropertiesPrefix), something like
	 * this can be done:
	 * @code
	 * $object->color = "red";
	 * $object->width = 10;
	 * @endcode
	 * This will mean to set column col_color to "red" and column col_width to
	 * 10.
	 *
	 * @param string $name Property name (without prefix).
	 * @param string $value Value to be set.
	 * @return boolean Returns true when the value was successfully set in the
	 * database.
	 */
	public function __set($name, $value) {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Setting default value to be returned.
		$out = false;
		//
		// Checking that:
		//	- Read Only Mode is not activated.
		//	- The current object has no issues.
		//	- And the property to be edited is not a read only property.
		if(!$wcDefaults["read-only"] && $this->ok() && !in_array($name, $this->_PropertiesReadOnly)) {
			//
			// Building the real property name (table column name).
			$property = $this->_PropertiesPrefix.$name;
			//
			// If the property is not set in the current properties
			// list and it can be NULL, it is internally set as false.
			if(!isset($this->_info[$property]) && in_array($name, $this->_PropertiesNULL)) {
				$this->_info[$property] = false;
			}
			//
			// Checking if it's a valid property.
			if(isset($this->_info[$property])) {
				//
				// Creating an specific statement to update this
				// property.
				// @{
				$stmt = false;
				$stmtID = __CLASS__."::".__FUNCTION__."[{$property}]";
				if($this->_db->has($stmtID)) {
					$stmt = $this->_db->get($stmtID);
				} else {
					$prefix = $this->_PropertiesPrefix;
					$table = $this->_dbprefix.$this->_PropertiesTable;

					$query = "update  {$table}\n";
					$query .= "set     {$property} = :value\n";
					$query .= "where   {$prefix}group = :group\n";
					$query .= " and    {$prefix}id    = :id\n";
					$stmt = $this->_db->prepare($stmtID, $query);
				}
				// @}
				//
				// $value may not be appropriated for the database,
				// therefore $realValue will be built and send.
				$realValue = $value;
				//
				// If it is boolean property it must be either 'Y'
				// or 'N' (for true and false).
				if(in_array($name, $this->_PropertiesBoolean)) {
					$realValue = $value ? "Y" : "N";
				}
				//
				// If the property has an associated function that
				// manages it, it is used.
				if(isset($this->_PropertiesPresetFunc[$name])) {
					eval("\$realValue = {$this->_PropertiesPresetFunc[$name]}(\$realValue);");
				}
				//
				// Checking final settings.
				if($this->subSet($name, $value, $realValue)) {
					//
					// Building database parameters.
					$params = array(
						":value" => $realValue,
						":group" => $this->group,
						":id" => $this->id
					);
					//
					// Attempting to modify the property in
					// the database.
					if($stmt->execute($params)) {
						//
						// If there are no errors, cached
						// property is modified.
						$this->_info[$property] = $value;
						//
						// At this point, property was
						// successfully set.
						$out = true;
					}
				}
			} else {
				//
				// This point is reached when an asked property
				// was not found on the database at loading.
				trigger_error(__CLASS__.": Property '{$name}' does not exists", E_USER_WARNING);
			}
		} elseif(!$this->ok()) {
			//
			// This point is reached when there's something wrong with
			// the current object, or when it's not yet loaded.
			trigger_error(__CLASS__.": Object is not loaded", E_USER_WARNING);
			//	} elseif($wcDefaults["read-only"]) {
			//		//
			//		// For other cases, except Read Only Mode, this will be
			//		// the exception thrown.
			//		trigger_error(__CLASS__.": Property '{$name}' cannot be modified",
			// E_USER_WARNING);
		}
		//
		// Returning modification status.
		return $out;
	}
	public function group() {
		return $this->_group;
	}
	public function load($id, WCGroup &$group) {
		$this->_ok = false;
		$this->_info = array(
			"{$this->_PropertiesPrefix}id" => $id,
			"{$this->_PropertiesPrefix}group" => $group->id
		);
		$this->_group = $group;

		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__."[".$this->_PropertiesTable."]";
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$prefix = $this->_PropertiesPrefix;
			$table = $this->_dbprefix.$this->_PropertiesTable;

			$query = "select  *\n";
			$query .= "from    {$table}\n";
			$query .= "where   {$prefix}group = :group\n";
			$query .= " and    {$prefix}id    = :id\n";
			$stmt = $this->_db->prepare($stmtId, $query);
		}

		$params = array(
			":group" => $this->group,
			":id" => $this->id
		);

		$result = $stmt->execute($params);

		if($result && $stmt->rowCount() == 1) {
			$this->_info = $stmt->fetch();
			$this->_ok = true;

			foreach($this->_PropertiesBoolean as $property) {
				$prop = $this->_PropertiesPrefix.$property;
				$this->_info[$prop] = isset($this->_info[$prop]) ? $this->_info[$prop] == "Y" : false;
			}
		} elseif(!$result) {
			global $wcLog;

			$error = $stmt->errorInfo();
			$msg = __CLASS__."::".__FUNCTION__."(): There was an error trying to load id '{$id}' of group '{$this->group}' from table '{$this->_dbprefix}{$this->_PropertiesTable}'.";
			$msg .= " Error: [{$error[1]}] {$error[2]}";
			if($wcLog) {
				$wcLog->write($msg);
				///@todo check level;
			}
			trigger_error($msg, E_USER_WARNING);
		} elseif($stmt->rowCount() != 1) {
			global $wcLog;

			$msg = __CLASS__."::".__FUNCTION__."(): There was an error trying to load id '{$id}' of group '{$this->group}' from table '{$this->_dbprefix}{$this->_PropertiesTable}'.";
			$msg .= " Resulting rows count: ".$stmt->rowCount();
			if($wcLog) {
				$wcLog->write($msg);
				///@todo check level;
			}
			trigger_error($msg, E_USER_WARNING);
		}

		return $this->ok();
	}
	public function loadByName($name, WCGroup &$group) {
		$this->_ok = false;
		$this->_info = array($this->_PropertiesPrefix."group" => $group->id);
		$this->_group = $group;

		$stmt = null;
		$stmtId = __CLASS__."::".__FUNCTION__."[".$this->_PropertiesTable."]";
		if($this->_db->has($stmtId)) {
			$stmt = $this->_db->get($stmtId);
		} else {
			$prefix = $this->_PropertiesPrefix;
			$table = $this->_dbprefix.$this->_PropertiesTable;
			$cname = $this->_PropertiesNameColumn;

			$query = "select  {$prefix}id as id,\n";
			$query .= "        {$prefix}{$cname} as name\n";
			$query .= "from    {$table}\n";
			$query .= "where   {$prefix}group = :group\n";
			$query .= " and    {$prefix}{$cname} = :name\n";
			$stmt = $this->_db->prepare($stmtId, $query);
		}

		$params = array(
			":group" => $this->group,
			":name" => $name
		);

		$result = $stmt->execute($params);

		if($result && $stmt->rowCount() == 1) {
			$row = $stmt->fetch();
			//
			// $name == $row["name"]:
			// name is checked only to ensure case sensitive match.
			if($name == $row["name"]) {
				$this->load($row["id"], $group);
			}
		} elseif(!$result) {
			global $wcLog;

			$error = $stmt->errorInfo();
			$msg = __CLASS__."::".__FUNCTION__."(): There was an error trying to load {$this->_PropertiesNameColumn} '{$name}' of group '{$this->group}' from table '{$this->_dbprefix}{$this->_PropertiesTable}'.";
			$msg .= " Error: [{$error[1]}] {$error[2]}";
			if($wcLog) {
				$wcLog->write($msg);
				///@todo check level;
			}
			trigger_error($msg, E_USER_WARNING);
		} elseif($stmt->rowCount() != 1) {
			global $wcLog;

			$msg = __CLASS__."::".__FUNCTION__."(): There was an error trying to load {$this->_PropertiesNameColumn} '{$name}' of group '{$this->group}' from table '{$this->_dbprefix}{$this->_PropertiesTable}'.";
			$msg .= " Resulting rows count: ".$stmt->rowCount();
			if($wcLog) {
				$wcLog->write($msg);
				///@todo check level;
			}
			trigger_error($msg, E_USER_WARNING);
		}

		return $this->ok();
	}
	public function reload() {
		return $this->load($this->id, $this->_group);
	}
	/**
	 * This method remove the represented object from the database.
	 *
	 * @return boolean Returns true when it was successfully removed.
	 */
	public function remove() {
		//
		// Loading global pointers.
		global $wcDefaults;
		//
		// Setting a default value to be returned.
		$out = false;
		//
		// Checking that Read Only Mode is not activated.
		if(!$wcDefaults["read-only"]) {
			//
			// Creating a statement to remove this object.
			// @{
			$stmt = null;
			$stmtId = __CLASS__."::".__FUNCTION__."[{$this->_PropertiesTable}]";
			if($this->_db->has($stmtId)) {
				$stmt = $this->_db->get($stmtId);
			} else {
				$prefix = $this->_PropertiesPrefix;
				$table = $this->_dbprefix.$this->_PropertiesTable;

				$query = "delete from {$table}\n";
				$query .= "where       {$prefix}group = :group\n";
				$query .= " and        {$prefix}id    = :id\n";
				$stmt = $this->_db->prepare($stmtId, $query);
			}
			// @}
			//
			// Building database parameters.
			$params = array(
				":group" => $this->group,
				":id" => $this->id
			);
			//
			// Attempting to remove it.
			if($stmt->execute($params)) {
				//
				// At this point, the object was successfully
				// removed, basic values and returning value are
				// set.
				// @{
				$this->_ok = false;
				$this->_info = array();
				$this->_group = null;

				$out = true;
				// @}
			}
		}
		//
		// Returning removal result.
		return $out;
	}
	//
	// Protected Methods
}
?>